package com.kmzx.one.project.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.kmzx.one.common.exceptions.NoSuchObjectException;
import com.kmzx.one.common.utils.DateTimeUtils;
import com.kmzx.one.project.entity.RankTab;
import com.kmzx.one.project.entity.UserInvite;
import com.kmzx.one.project.mapper.RankTabMapper;
import com.kmzx.one.project.mapper.UserInviteMapper;
import com.kmzx.one.project.mapper.UserLoggerMapper;
import com.kmzx.one.project.mapper.UserRankMapper;
import com.kmzx.one.project.others.common.UserLogin;
import com.kmzx.one.project.others.dso.UserRankDso;
import com.kmzx.one.project.others.dto.FansInfo;
import com.kmzx.one.project.others.dto.UserFansPageInfo;
import com.kmzx.one.project.others.dto.UserRankMoreInfo;
import com.kmzx.one.project.service.UserFanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class UserFanServiceImpl implements UserFanService {

    @Autowired
    private UserRankMapper userRankMapper;
    @Autowired
    private UserInviteMapper userInviteMapper;
    @Autowired
    private RankTabMapper rankTabMapper;

    @Autowired
    private UserLoggerMapper userLoggerMapper;


    @Override
    public List<FansInfo> findUserFans(String userId, Integer pageNum, Integer pageSize, String nickName) throws Exception {
        PageHelper.startPage(pageNum, pageSize, true);
        Page<FansInfo> pager = userInviteMapper.selectUserFansOne(userId, nickName);
        List<FansInfo> result = pager.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            setNextNameValue2(result, tabs);
        }
        return result;
    }

    @Override
    public List<FansInfo> findUserFans2(String userId, Integer pageNum, Integer pageSize, String nickName, Integer sorts) throws Exception {
        //
        List<FansInfo> list = userInviteMapper.findOldFansInfo(userId, nickName);
        if (sorts == 1) {
            if (list != null && list.size() > 0) {
                List<FansInfo> fansInfos = backToDatas(1, list, list);
                list = fansInfos;
            }
        } else if (sorts == 2) {
            if (list != null && list.size() > 0) {
                List<FansInfo> fansInfos = backToDatas(2, list, list);
                list = fansInfos;
            }
        } else {
            if (list != null && list.size() > 0) {
                List<FansInfo> fansInfos = backToDatas(0, list, list);
                list = fansInfos;
            }
        }


        if (list != null && list.size() > 0) {
            int totalLen = list.size();
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            if (totalLen < pageSize) {
                if (pageNum >= 2) {
                    return Collections.emptyList();
                } else {
                    setNextNameValue2(list, tabs);
                    return list;
                }
            }else {
                Integer start = pageSize * (pageNum - 1);
                Integer middle = pageNum * pageSize;
                if (middle < totalLen){
                    List<FansInfo> send = list.subList(start, middle);
                    setNextNameValue2(list, tabs);
                    return send;
                }else {
                    List<FansInfo> send = list.subList(start, totalLen);
                    setNextNameValue2(list, tabs);
                    return send;
                }
            }
        } else {
            return list;
        }

    }

    private List<FansInfo> findOldFansInfo(String userId, Integer pageNum, Integer pageSize, String nickName, Integer sorts) {
        PageHelper.startPage(pageNum, pageSize, true);
        Page<FansInfo> pager = userInviteMapper.selectUserFansOne(userId, nickName);
        List<FansInfo> result = pager.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            setNextNameValue2(result, tabs);
        }
        result = backToDatas(sorts, result, result);
        return result;
    }


    @Override
    public List<FansInfo> findUserFansSearch(String userId, Integer pageNum, Integer pageSize, String nickName) throws Exception {
        PageHelper.startPage(pageNum, pageSize, true);
        Page<FansInfo> pager = userInviteMapper.selectUserFansSearch(userId, nickName);
        List<FansInfo> result = pager.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            setNextNameValue2(result, tabs);
        }
        return result;
    }

    @Override
    public List<FansInfo> findUserFansSearch2(String userId, Integer pageNum, Integer pageSize, String nickName, Integer sorts) throws Exception {
        PageHelper.startPage(pageNum, pageSize, true);
        Page<FansInfo> pager = userInviteMapper.selectUserFansSearch(userId, nickName);
        List<FansInfo> result = pager.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            setNextNameValue2(result, tabs);
        }
        result = backToDatas(sorts, result, result);
        return result;
    }

    // @Override
//    public List<FansInfo> findUserFansPagers(String userId, Integer pageNum, Integer pageSize, Integer kinds) throws Exception {
//        List<FansInfo> list = haveNext(userId);
//        List<FansInfo> list1 = new ArrayList<>();
//        for (int i = 0; i < list.size(); i++) {
//            if (kinds - 1 == list.get(i).getLevels()) {
//                list1.add(list.get(i));
//            }
//        }
//        if (!CollectionUtils.isEmpty(list1)) {
//            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
//            setNextNameValue2(list1, tabs);
//        }
//        return list1;
//    }

    public List<FansInfo> findUserFansEn(String userId, Integer pageNum, Integer pageSize, Integer sorts) {
        List<FansInfo> list = findNextFans(userId);
        if (list != null && list.size() > 0) {
            List<FansInfo> collect = list.stream().sorted(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()).thenComparing(FansInfo::getCom, Comparator.reverseOrder())).collect(Collectors.toList());
            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
            int totalLen = list.size();
            if (totalLen < pageSize) {
                if (pageNum >= 2) {
                    return Collections.emptyList();
                } else {
                    setNextNameValue2(list, tabs);
                    return backToDatas(sorts, list, collect);
                }
            } else {
                Integer start = pageSize * (pageNum - 1);
                Integer middle = pageNum * pageSize;
                collect = backToDatas(sorts, list, collect);
                if (middle < totalLen) {
                    List<FansInfo> send = collect.subList(start, middle);
                    setNextNameValue2(list, tabs);
                    return send;
                } else {
                    List<FansInfo> send = collect.subList(start, totalLen);
                    setNextNameValue2(list, tabs);
                    return send;
                }
            }
        }
        return null;
    }


    @Override
    public UserRankMoreInfo findMyManager(String userId) throws Exception {

        List<UserInvite> userInvites = userInviteMapper.selectUserInviteByUserId(userId);
        if (CollectionUtils.isEmpty(userInvites)) {
            return null;
        }
        String fromUser = userInvites.get(0).getFromUser();
        UserRankMoreInfo myManager = userInviteMapper.selectMyManager(fromUser);
        int rankNum = myManager.getRankNum();
        if (rankNum != 3) {
            List<UserRankDso> tabs = userRankMapper.selectAllRankTabs();
            for (int i = 0; i < tabs.size(); i++) {
                if (tabs.get(i).getRankId().equals(myManager.getRankId()) && i != tabs.size() - 1) {
                    myManager.setNextName(tabs.get(i + 1).getRankName());
                    break;
                }
            }
        }

        int num = userInviteMapper.selectUserInviteNum(fromUser);
        myManager.setChild(num);
        return myManager;
    }

    //@Override
//    public List<FansInfo> findUserOlderFans(String userId, Integer pageNum, Integer pageSize) throws Exception {
//        PageHelper.startPage(pageNum, pageSize, true);
//        Page<FansInfo> pager = userInviteMapper.findUserFansOld(userId);
//        List<FansInfo> result = pager.getResult();
//        if (!CollectionUtils.isEmpty(result)) {
//            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
//            setNextNameValue2(result, tabs);
//            setNextNameValues(result);
//        }
//        return result;
//    }


    public void setNextNameValue2(List<FansInfo> result, List<RankTab> tabs) {
        HashMap<Integer, BigDecimal> tabss = new HashMap<>();
        HashMap<Integer, String> names = new HashMap<>();
        if (!CollectionUtils.isEmpty(tabs)) {
            for (RankTab tab : tabs) {
                tabss.put(tab.getRankNumber(), tab.getRankPay());
                names.put(tab.getRankNumber(), tab.getRankName());
            }
        }
        for (FansInfo FansInfo : result) {
            int levels = FansInfo.getLevels();
            BigDecimal growths = FansInfo.getGrowths();
            if (levels != 3) {
                BigDecimal bigDecimal = tabss.get(levels);

                BigDecimal needs = bigDecimal.subtract(growths);
                FansInfo.setNextName(names.get(levels + 1));
                FansInfo.setNeeds(needs);
            }
        }
    }

//    public List<FansInfo> haveNext(String userId) {
//        Page<FansInfo> pager = userInviteMapper.selectUserFans(userId, null);
//        List<FansInfo> result = pager.getResult();
//        for (int i = 0; i < result.size(); i++) {
//            List<FansInfo> list1 = haveNext(result.get(i).getUserId());
//            result.addAll(list1);
//        }
//        return result;
//    }

    public List<FansInfo> findNextFans(String userId) {
        Page<FansInfo> pager = userInviteMapper.selectUserFans2(userId, null);
        List<FansInfo> result = pager.getResult();
        for (int i = 0; i < result.size(); i++) {
            if (result.get(i).getChild() > 0) {
                List<FansInfo> list1 = findNextFans(result.get(i).getUserId());
                result.addAll(list1);
            }
        }
        return result;
    }


    @Override
    public List<FansInfo> findUserFansEntry(String userId, Integer pageNum, Integer pageSize) throws Exception {
//        PageHelper.startPage(pageNum, pageSize);
//        Page<FansInfo> page = userInviteMapper.selectUserFans2(userId, null);
//        List<FansInfo> result = page.getResult();
//        if (!CollectionUtils.isEmpty(result)) {
//            List<RankTab> tabs = rankTabMapper.selectAllRankTab();
//            setNextNameValue2(result, tabs);
//        }
//        return result;

        List<FansInfo> en = findUserFansEn(userId, pageNum, pageSize, 1);
        if (en != null && en.size() > 0) {
            List<FansInfo> collect = en.stream().distinct().collect(Collectors.toList());
            return collect;
        } else {
            return null;
        }
    }


    @Override
    public List<FansInfo> findUserFansEntry2(String userId, Integer pageNum, Integer pageSize, Integer sorts) throws Exception {
        List<FansInfo> en = findUserFansEn(userId, pageNum, pageSize, sorts);
        if (en != null && en.size() > 0) {
            List<FansInfo> collect = en.stream().distinct().collect(Collectors.toList());
            return collect;
        } else {
            return null;
        }
    }

    @Override
    public UserFansPageInfo searchUserFansByNickName(String nickName, String userId, Integer pageNum, Integer pageSize) throws Exception {
        String regExp = "^([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])$";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(pageNum.toString());
        if (!m.matches()) {
            throw new NoSuchObjectException(204, "参数异常");
        }

        if (!p.matcher(pageSize.toString()).matches()) {
            throw new NoSuchObjectException(204, "参数异常");
        }


        UserFansPageInfo info = new UserFansPageInfo(pageNum, pageSize, 0, pageNum);
        Integer ch = userInviteMapper.checkLikeNickName(nickName);
        if (ch == 0) {
            return info;
        }
        List<FansInfo> fansInfos1 = rankTabMapper.getAllFans(nickName);
        List<FansInfo> toResult = new ArrayList<>();
        if (fansInfos1 != null) {
            for (int i = 0; i < fansInfos1.size(); i++) {
                if (fansInfos1.get(i).getpUserId() != null) {
                    Boolean ms = haveNextNickNameLike1(fansInfos1.get(i).getpUserId(), userId);
                    if (ms) {
                        toResult.add(fansInfos1.get(i));
                    }
                }
            }
        }
        if (toResult != null && toResult.size() > 0) {
            int totalLen = toResult.size();
            info.setTotal(totalLen);

//            toResult.sort(Comparator.comparing(FansInfo::getCom).reversed());
            if (totalLen < pageSize) {
                List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                setNextNameValue2(toResult, tabs);
                for (FansInfo fansInfo : toResult) {
                    String selfId = fansInfo.getUserId();
                    int num = userInviteMapper.selectUserInviteNum(selfId);
                    fansInfo.setChild(num);
                }
                //
                List<FansInfo> collect = toResult.stream().sorted(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()).thenComparing(FansInfo::getCom, Comparator.reverseOrder())).collect(Collectors.toList());
                info.setChildren(collect);

                return info;
            } else {
                Integer start = pageSize * (pageNum - 1);
                Integer middle = pageNum * pageSize;
                List<FansInfo> collect = toResult.stream().sorted(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()).thenComparing(FansInfo::getCom, Comparator.reverseOrder())).collect(Collectors.toList());
                if (middle < totalLen) {

                    List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                    setNextNameValue2(toResult, tabs);
                    for (FansInfo fansInfo : toResult) {
                        String selfId = fansInfo.getUserId();
                        int num = userInviteMapper.selectUserInviteNum(selfId);
                        fansInfo.setChild(num);
                    }

                    List<FansInfo> send = collect.subList(start, middle);
                    info.setChildren(send);


                } else {
                    List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                    setNextNameValue2(toResult, tabs);
                    for (FansInfo fansInfo : toResult) {
                        String selfId = fansInfo.getUserId();
                        int num = userInviteMapper.selectUserInviteNum(selfId);
                        fansInfo.setChild(num);
                    }

                    List<FansInfo> send = collect.subList(start, totalLen);
                    info.setChildren(send);
                }

                return info;
            }
        }
        if (info != null && info.getChildren() != null && info.getChildren().size() > 0) {
            List<FansInfo> children = info.getChildren();
            List<FansInfo> collect = children.stream().distinct().collect(Collectors.toList());
            info.setChildren(collect);
        }
        return info;
    }

    @Override
    public UserFansPageInfo searchUserFansByNickName2(String nickName, String userId, Integer pageNum, Integer pageSize, Integer sorts) throws Exception {
        String regExp = "^([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])$";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(pageNum.toString());
        if (!m.matches()) {
            throw new NoSuchObjectException(204, "参数异常");
        }

        if (!p.matcher(pageSize.toString()).matches()) {
            throw new NoSuchObjectException(204, "参数异常");
        }


        UserFansPageInfo info = new UserFansPageInfo(pageNum, pageSize, 0, pageNum);
        Integer ch = userInviteMapper.checkLikeNickName(nickName);
        if (ch == 0) {
            return info;
        }
        List<FansInfo> fansInfos1 = rankTabMapper.getAllFans(nickName);
        List<FansInfo> toResult = new ArrayList<>();
        if (fansInfos1 != null) {
            for (int i = 0; i < fansInfos1.size(); i++) {
                if (fansInfos1.get(i).getpUserId() != null) {
                    Boolean ms = haveNextNickNameLike1(fansInfos1.get(i).getpUserId(), userId);
                    if (ms) {
                        toResult.add(fansInfos1.get(i));
                    }
                }
            }
        }
        if (toResult != null && toResult.size() > 0) {
            int totalLen = toResult.size();
            info.setTotal(totalLen);

//            toResult.sort(Comparator.comparing(FansInfo::getCom).reversed());
            if (totalLen < pageSize) {
                pageNum = pageNum - 1;
                if (pageNum * pageSize <= totalLen) {
                    List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                    setNextNameValue2(toResult, tabs);
                    for (FansInfo fansInfo : toResult) {
                        String selfId = fansInfo.getUserId();
                        int num = userInviteMapper.selectUserInviteNum(selfId);
                        fansInfo.setChild(num);
                    }
                    //
                    List<FansInfo> collect = toResult.stream().sorted(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()).thenComparing(FansInfo::getCom, Comparator.reverseOrder())).collect(Collectors.toList());

                    collect = backToDatas(sorts, toResult, collect);
                    info.setChildren(collect);

                } else {
                    info.setTotal(0);
                    info.setChildren(null);
                }

                return info;
            } else {
                Integer start = pageSize * (pageNum - 1);
                Integer middle = pageNum * pageSize;
                List<FansInfo> collect = toResult.stream().sorted(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()).thenComparing(FansInfo::getCom, Comparator.reverseOrder())).collect(Collectors.toList());
                if (middle < totalLen) {

                    List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                    setNextNameValue2(toResult, tabs);
                    for (FansInfo fansInfo : toResult) {
                        String selfId = fansInfo.getUserId();
                        int num = userInviteMapper.selectUserInviteNum(selfId);
                        fansInfo.setChild(num);
                    }
                    collect = backToDatas(sorts, toResult, collect);
                    List<FansInfo> send = collect.subList(start, middle);
                    info.setChildren(send);


                } else {
                    if (start <= totalLen) {
                        List<RankTab> tabs = rankTabMapper.selectAllRankTab();
                        setNextNameValue2(toResult, tabs);
                        for (FansInfo fansInfo : toResult) {
                            String selfId = fansInfo.getUserId();
                            int num = userInviteMapper.selectUserInviteNum(selfId);
                            fansInfo.setChild(num);
                        }
                        collect = backToDatas(sorts, toResult, collect);
                        List<FansInfo> send = collect.subList(start, totalLen);
                        info.setChildren(send);
                    } else {
                        info.setChildren(null);
                    }
                }
                return info;
            }
        }
        if (info != null && info.getChildren() != null && info.getChildren().size() > 0) {
            List<FansInfo> children = info.getChildren();
            List<FansInfo> collect = children.stream().distinct().collect(Collectors.toList());
            info.setChildren(collect);
        }
        return info;
    }


    private Boolean haveNextNickNameLike1(String userId, String pUserId) {
        if (userId.equals(pUserId)) {
            return true;
        } else {
            String fromId = rankTabMapper.getFromId(userId);
            if (fromId != null) {
                return haveNextNickNameLike1(fromId, pUserId);
            } else {
                if (pUserId.equals(userId)) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }


    public List<FansInfo> backToDatas(Integer sorts, List<FansInfo> list, List<FansInfo> collect) {
        if (list != null && list.size() > 0) {
            if (sorts == 1) {
                List<UserLogin> logins = userLoggerMapper.selectUserUserLogin2(list);
                if (logins != null && logins.size() > 0) {

                    for (FansInfo fansInfo : collect) {
                        for (UserLogin login : logins) {
                            if (fansInfo.getUserId().equals(login.getUserId())) {
                                fansInfo.setLogint(login.getLoginTime());
                            }
                        }
                    }
                }
                for (FansInfo fansInfo : collect) {
                    Date logint = fansInfo.getLogint();
                    if (logint == null) {
                        if (fansInfo.getCom() != null) {
                            fansInfo.setLogint(fansInfo.getCom());
                        } else {
                            fansInfo.setLogint(new Date(1556640000000l));
                        }
                    }
                    fansInfo.setIndex(1);
                    fansInfo.setLoginTime(DateTimeUtils.formatLocalDateTime(fansInfo.getLogint()));
                }
                collect.sort(Comparator.comparing(FansInfo::getLogint, Comparator.reverseOrder()));
            } else if (sorts == 2) {
                List<FansInfo> toPayUser = collect.stream().filter(ss -> ss.getGrowths().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                if (toPayUser != null && toPayUser.size() > 0) {
                    List<UserLogin> logins = userLoggerMapper.selectUserUserPay2(toPayUser);
                    if (logins != null && logins.size() > 0) {

                        for (FansInfo fansInfo : collect) {
                            for (UserLogin login : logins) {
                                if (fansInfo.getUserId().equals(login.getUserId())) {
                                    fansInfo.setPayt(login.getPayTime());
                                }
                            }
                        }
                    }
                }
                for (FansInfo fansInfo : collect) {
                    Date logint = fansInfo.getPayt();
                    if (logint == null) {
                        fansInfo.setPayt(new Date(1556640000000l));
                    }
                    fansInfo.setIndex(2);
                    fansInfo.setPayTime(DateTimeUtils.formatLocalDateTime(fansInfo.getPayt()));
                }
                collect.sort(Comparator.comparing(FansInfo::getPayt, Comparator.reverseOrder()));
            } else if (sorts == 0) {
                collect.sort(Comparator.comparing(FansInfo::getChild, Comparator.reverseOrder()));
            }
        }
        return collect;
    }

}
